import type { App } from "vue";

/* 需要注意的是，本局部监听，只适用于单个的内容中等的，内部嵌套中等的 div ，如果内容太多，可能会有性能问题 */

interface EleObject {
  el: null | Element;
  children: Array<any>;
}

let baseElement: Element | null;
let callback: any = null; // 触发的回调函数
let timer: any = null; // 定时器
let laterTime: number = 300; // 延时器延时触发

// 外层 dom 变化大小的时候触发回调函数
const ob = new ResizeObserver((entries: any) => {
  if (callback) {
    if (!timer) {
      timer = setTimeout(() => {
        callback();
        timer = null;
      }, laterTime);
    }
  }
});

// 获取 dom 树，并且更改 dom 树上的每一个节点
// el 外层参数，正常也取最外层参数；但是由于递归调用过程中会不断变化 el，因此还需要一个基础的 el
// baseEl 基础参数, 这个取最外层参数
const analysisElementTree = (
  el: Element,
  baseEl: Element | any = baseElement
) => {
  baseEl.style.containerType = "size";
  const baseWidth = Number(
    window.getComputedStyle(baseEl).width.replace("px", "")
  );
  let domTree: EleObject = {
    el: null,
    children: [],
  };
  if (!el) return;
  domTree.el = el;
  if (el.children.length === 0) {
    domTree.children = [];
  } else {
    [...el.children].forEach((it: any) => {
      domTree.children.push({
        el: it,
        children: analysisElementTree(it),
      });
      if (
        window.getComputedStyle(it).width &&
        window.getComputedStyle(it).width != "auto"
      ) {
        const wNum = Number(
          window.getComputedStyle(it).width.replace("px", "")
        );
        it.style.width = (wNum * 100) / baseWidth + "cqw";
      }
      if (
        window.getComputedStyle(it).height &&
        window.getComputedStyle(it).height != "auto"
      ) {
        const hNum = Number(
          window.getComputedStyle(it).height.replace("px", "")
        );
        it.style.height = (hNum * 100) / baseWidth + "cqw";
      }
      if (
        window.getComputedStyle(it).fontSize &&
        window.getComputedStyle(it).fontSize != "auto"
      ) {
        const fNum = Number(
          window.getComputedStyle(it).fontSize.replace("px", "")
        );
        it.style.fontSize = (fNum * 100) / baseWidth + "cqw";
      }
    });
  }
  return domTree;
};

const vPartResize = {
  mounted: (el: Element, binding: any) => {
    if (
      binding.arg &&
      Number(binding.arg) != 0 &&
      !Number.isNaN(Number(binding.arg))
    ) {
      laterTime = Number(binding.arg);
    }
    baseElement = el;
    baseElement && analysisElementTree(el);
    if (binding.value && typeof binding.value === "function") {
      // 如果有需要回调函数 callback，那么就调取监听大小函数，否则不调取
      callback = binding.value;
      callback && ob.observe(el);
    }
  },
  unmounted(el: Element, binding: any) {
    if (binding.value && typeof binding.value === "function") {
      // 如果有回调函数 callback，那么就卸载监听
      ob.unobserve(el);
    }
  },
};

export function setPartResize(app: App) {
  app.directive("dyxPartResize", vPartResize);
}
